package com.example.demo.config.login;

import java.io.IOException;
import java.io.InputStream;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.example.demo.bean.User;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 登陆时处理数据格式，UsernamePasswordAuthenticationFilter这个类的
 * 
 * @author Administrator
 *
 */
public class CustomAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

	@SuppressWarnings("finally")
	@Override
	public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
			throws AuthenticationException {

		// attempt Authentication when Content-Type is json
		if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
				|| request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {

			// use jackson to deserialize json
			ObjectMapper mapper = new ObjectMapper();
			UsernamePasswordAuthenticationToken authRequest = null;
			try (InputStream is = request.getInputStream()) {

				// mapper.readValue(request的请求，带有参数的类.class)
				// 这句相当于request.getParameter(Object.class.getLocal.get其中的对象)
				User authenticationBean = mapper.readValue(is, User.class);

				// 拼接对象
				authRequest = new UsernamePasswordAuthenticationToken(authenticationBean.getUsername(),
						authenticationBean.getPassword());
			} catch (IOException e) {
				e.printStackTrace();
				authRequest = new UsernamePasswordAuthenticationToken("", "");
			} finally {
				setDetails(request, authRequest);
				return this.getAuthenticationManager().authenticate(authRequest);
			}
		}

		// transmit it to UsernamePasswordAuthenticationFilter
		else {
			return super.attemptAuthentication(request, response);
		}
	}

	/**
	 * 这两个方法也可以实现登陆成功和，登陆失败的处理<br>
	 * UsernamePasswordAuthenticationFilter的父类AbstractAuthenticationProcessingFilter拥有<br>
	 * 
	 * private AuthenticationSuccessHandler successHandler = new
	 * SavedRequestAwareAuthenticationSuccessHandler();<br>
	 * 
	 * private AuthenticationFailureHandler failureHandler = new
	 * SimpleUrlAuthenticationFailureHandler(); <br>
	 * 
	 * 这两个类的实现 <br>
	 * successHandler.onAuthenticationSuccess(request, response, authResult);
	 * failureHandler.onAuthenticationFailure(request, response, failed);
	 * 
	 * successfulAuthentication：在源码中是将用户信息放入Authentication中，onAuthenticationSuccess是判断返回的url和session的处理，并返回
	 */
	@Override
	protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
			Authentication authResult) throws IOException, ServletException {
		// TODO Auto-generated method stub
		super.successfulAuthentication(request, response, chain, authResult);
	}

	/**
	 * 登陆失败的处理
	 * 
	 * unsuccessfulAuthentication：在源码中清除session用，onAuthenticationFailure也是在判断url和session并返回
	 */
	@Override
	protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException failed) throws IOException, ServletException {
		// TODO Auto-generated method stub
		super.unsuccessfulAuthentication(request, response, failed);
	}
}
